package config

import (
	"fmt"
	"cloud_worm/util/uconfig"
	"sync"
	"encoding/json"
	"github.com/golang/glog"
	"cloud_worm/util/unet"
	"strings"
)

type StartModer interface {
	Parse(container uconfig.ConfContainer) error
}

type WormConfig struct {
	RunMode 		string			`json:"run_mode"`			// 运行环境
	
	Version 		int				`json:"version"`
	LocalNet 		string			`json:"local_net"`			// 本地地址的网段采用逗号分割
	LocalAddr 		string			`json:"local_addr"`			// 本地的ip地址

	StartMode 		string			`json:"start_mode"`			// 启动模式
	StartConfig 	StartModer 		`json:"start_config"`
}

const (
	ClientStartMode = "client"
	HttpSrvStartMode = "httpsrv"
)

func (w *WormConfig) ReadConfig(fileName string) error {
	config := uconfig.InitConfig{}
	container, err := config.Parse(fileName)
	if err != nil {
		return err
	}

	w.RunMode = container.String("run_mode")
	if w.RunMode == "" {
		return fmt.Errorf("no run_mode exist")
	}
	w.StartMode = container.String("start_mode")
	if w.StartMode == "" {
		return fmt.Errorf("no start_mode exist")
	}
	w.LocalNet = container.String("local_net")
	if w.LocalNet == "" {
		return fmt.Errorf("no local_net exist")
	}

	if w.StartMode == ClientStartMode {
		w.StartConfig = &ClientConfig{}
		if err := w.StartConfig.Parse(container); err != nil {
			return err
		}
	} else if w.StartMode == HttpSrvStartMode {
		w.StartConfig = &HttpSrvConfig{}
		if err := w.StartConfig.Parse(container); err != nil {
			return err
		}
	} else {
		return fmt.Errorf("start mode error")
	}

	return nil
}

func (w *WormConfig) IsClient() bool {
	if w.StartMode == ClientStartMode {
		return true
	}
	return false
}

func (w *WormConfig) IsHttpSrv() bool {
	if w.StartMode == HttpSrvStartMode {
		return true
	}
	return false
}

var CfgInst *WormConfig
var cfgOnce sync.Once

func init()  {
	cfgOnce.Do(func() {
		CfgInst = &WormConfig{}
	})
}

func LoadConfig(filePath string, version int) error {
	if err := CfgInst.ReadConfig(filePath); err != nil {
		return err
	}
	CfgInst.Version = version

	SetLocalAddrFilter(CfgInst.LocalNet)
	CfgInst.LocalAddr = LocalIP()
	if CfgInst.LocalAddr == "" {
		return fmt.Errorf("local ip get error")
	}

	data, _ := json.Marshal(CfgInst)
	glog.Info(string(data))
	return nil
}

func LocalIP() string {

	ips, err := unet.AllIPs()
	if err != nil {
		glog.Errorf("lookup all ips error: %s", err.Error())
		return ""
	}

	return unet.Intranet(ips)
}

// TODO：添加其他的规则
func SetLocalAddrFilter(localNet string)  {

	for _, item := range strings.Split(localNet, ";") {
		item := strings.TrimSpace(item)
		if len(item) == 0 {
			continue
		}

		filterFunc := func(input string) bool {
			if strings.HasPrefix(input, item) {
				return true
			}
			return false
		}
		unet.RegisterParser(item, filterFunc)
	}

	return
}